<?php

require_once(sfConfig::get('sf_symfony_lib_dir') . '/helper/JavascriptBaseHelper.php');

/**
* @desc  Load jquery library in header
* 
*/


sfContext::getInstance()->getResponse()->addJavascript(sfConfig::get('sf_jquery_web_dir', '/sfJqueryPlugin/js/jquery-1.2.6.min.js'), 'first');


/**
 * Add a jQuery Plugin on the head DOM after the jQuery call
 * The default directory is jq/plugins/
 *
 * Examples:
 *   <?php echo jq_add_plugin(array('plugin1', 'plugin2')) ?>
 */
function jq_add_plugin($options = array()) {
    foreach ( $options as $o ) {
        sfContext::getInstance ()->getResponse ()->addJavascript (sfConfig::get('sf_jquery_web_dir', '/sfJqueryPlugin/js/') .'plugins/' . $o );
    }
}
         

/**
   * Periodically calls the specified url ('url') every 'frequency' seconds (default is 10).
   * Usually used to update a specified div ('update') with the results of the remote call.
   * The options for specifying the target with 'url' and defining callbacks is the same as 'link_to_remote()'.
   */
function jq_periodically_call_remote($options = array())
{
  $frequency = isset($options['frequency']) ? $options['frequency'] : 10; // every ten seconds by default
  $code = 'setInterval(function() {'.jq_remote_function($options).'}, '.($frequency * 1000).')';

  return javascript_tag($code);
}

  /**
   * Returns an html button to a remote action defined by 'url' (using the
   * 'url_for()' format) that's called in the background using XMLHttpRequest.
   *
   * See link_to_remote() for details.
   *
   */
  function jq_button_to_remote($name, $options = array(), $html_options = array())
  {
    return jq_button_to_function($name, jq_remote_function($options), $html_options);
  }


/**
   * Returns a link to a remote action defined by 'url'
   * (using the 'url_for()' format) that's called in the background using
   * XMLHttpRequest. The result of that request can then be inserted into a
   * DOM object whose id can be specified with 'update'.
   * Usually, the result would be a partial prepared by the controller with
   * either 'render_partial()'.
   *
   * Examples:
   *  <?php echo link_to_remote('Delete this post'), array(
   *    'update' => 'posts',
   *    'url'    => 'destroy?id='.$post.id,
   *  )) ?>
   *  <?php echo link_to_remote(image_tag('refresh'), array(
   *    'update' => 'emails',
   *    'url'    => '@list_emails',
   *  )) ?>
   *
   * You can also specify a hash for 'update' to allow for
   * easy redirection of output to an other DOM element if a server-side error occurs:
   *
   * Example:
   *  <?php echo link_to_remote('Delete this post', array(
   *      'update' => array('success' => 'posts', 'failure' => 'error'),
   *      'url'    => 'destroy?id='.$post.id,
   *  )) ?>
   *
   * Optionally, you can use the 'position' parameter to influence
   * how the target DOM element is updated. It must be one of
   * 'before', 'top', 'bottom', or 'after'.
   *
   * By default, these remote requests are processed asynchronous during
   * which various JavaScript callbacks can be triggered (for progress indicators and
   * the likes). All callbacks get access to the 'request' object,
   * which holds the underlying XMLHttpRequest.
   *
   * To access the server response, use 'request.responseText', to
   * find out the HTTP status, use 'request.status'.
   *
   * If you are using JSON, you can access it via the 'data' parameter
   *
   * Example:
   *  <?php echo jq_link_to_remote($word, array(
   *    'url'      => '@undo?n='.$word_counter,
   *    'complete' => 'undoRequestCompleted(request)'
   *  )) ?>
   *
   * The callbacks that may be specified are (in order):
   *
   * 'loading'                 Called when the remote document is being
   *                           loaded with data by the browser.
   * 'loaded'                  Called when the browser has finished loading
   *                           the remote document.
   * 'interactive'             Called when the user can interact with the
   *                           remote document, even though it has not
   *                           finished loading.
   * 'success'                 Called when the XMLHttpRequest is completed,
   *                           and the HTTP status code is in the 2XX range.
   * 'failure'                 Called when the XMLHttpRequest is completed,
   *                           and the HTTP status code is not in the 2XX
   *                           range.
   * 'complete'                Called when the XMLHttpRequest is complete
   *                           (fires after success/failure if they are present).,
   *
   * You can further refine 'success' and 'failure' by adding additional
   * callbacks for specific status codes:
   *
   * Example:
   *  <?php echo jq_link_to_remote($word, array(
   *       'url'     => '@rule',
   *       '404'     => "alert('Not found...? Wrong URL...?')",
   *       'failure' => "alert('HTTP Error ' + request.status + '!')",
   *  )) ?>
   *
   * A status code callback overrides the success/failure handlers if present.
   *
   * If you for some reason or another need synchronous processing (that'll
   * block the browser while the request is happening), you can specify
   * 'type' => 'synchronous'.
   *
   * You can customize further browser side call logic by passing
   * in JavaScript code snippets via some optional parameters. In
   * their order of use these are:
   *
   * 'confirm'             Adds confirmation dialog.
   * 'condition'           Perform remote request conditionally
   *                       by this expression. Use this to
   *                       describe browser-side conditions when
   *                       request should not be initiated.
   * 'before'              Called before request is initiated.
   * 'after'               Called immediately after request was
   *                       initiated and before 'loading'.
   * 'submit'              Specifies the DOM element ID that's used
   *                       as the parent of the form elements. By
   *                       default this is the current form, but
   *                       it could just as well be the ID of a
   *                       table row or any other DOM element.
   */
function jq_link_to_remote($name, $options = array(), $html_options = array())
{
  return jq_link_to_function($name, jq_remote_function($options), $html_options);
}

/**
   * Returns a Javascript function (or expression) that will update a DOM element '$element_id'
   * according to the '$options' passed.
   *
   * Possible '$options' are:
   * 'content'            The content to use for updating. Can be left out if using block, see example.
   * 'action'             Valid options are 'update' (assumed by default), 'empty', 'remove'
   * 'position'           If the 'action' is 'update', you can optionally specify one of the following positions:
   *                      'before', 'top', 'bottom', 'after'.
   *
   * Example:
   *   <?php echo javascript_tag(
   *      update_element_function('products', array(
   *            'position' => 'bottom',
   *            'content'  => "<p>New product!</p>",
   *      ))
   *   ) ?>
   */
   
function jq_update_element_function($element_id, $options = array())
{
  

  $content = escape_javascript(isset($options['content']) ? $options['content'] : '');

  $value = isset($options['action']) ? $options['action'] : 'update';
  switch ($value)
  {
    case 'update':
      $updateMethod = _update_method(isset($options['position']) ? $options['position'] : '');
      $javascript_function = "jQuery('#$element_id').$updateMethod('$content')";
      break;

    case 'empty':
      $javascript_function = "jQuery('#$element_id').empty()";
      break;

    case 'remove':
      $javascript_function = "jQuery('#$element_id').remove()";
      break;

    default:
      throw new sfException('Invalid action, choose one of update, remove, empty');
  }

  $javascript_function .= ";\n";

  return (isset($options['binding']) ? $javascript_function.$options['binding'] : $javascript_function);
}

/**
   * Returns the javascript needed for a remote function.
   * Takes the same arguments as 'link_to_remote()'.
   *
   * Example:
   *   <select id="options" onchange="<?php echo remote_function(array('update' => 'options', 'url' => '@update_options')) ?>">
   *     <option value="0">Hello</option>
   *     <option value="1">World</option>
   *   </select>
   */
function jq_remote_function($options)
{
    // Defining elements to update
  if (isset($options['update']) && is_array($options['update']))
  {
    // On success, update the element with returned data
    if (isset($options['update']['success'])) $update_success = "#".$options['update']['success'];

    // On failure, execute a client-side function
    if (isset($options['update']['failure'])) $update_failure = $options['update']['failure'];
  }
  else if (isset($options['update'])) $update_success = "#".$options['update'];

  // Update method
  $updateMethod = _update_method(isset($options['position']) ? $options['position'] : '');

  // Callbacks
  if (isset($options['loading'])) $callback_loading = $options['loading'];
  if (isset($options['complete'])) $callback_complete = $options['complete'];
  if (isset($options['success'])) $callback_success = $options['success'];

  $execute = 'false';
  if ((isset($options['script'])) && ($options['script'] == '1')) $execute = 'true';

  // Data Type
  if (isset($options['dataType']))
  {
    $dataType = $options['dataType'];
  }
  elseif ($execute)
  {
    $dataType = 'html';
  }
  else
  {
    $dataType = 'text';
  }

  // POST or GET ?
  $method = 'POST';
  if ((isset($options['method'])) && (strtoupper($options['method']) == 'GET')) $method = $options['method'];

  // async or sync, async is default
  if ((isset($options['type'])) && ($options['type'] == 'synchronous')) $type = 'false';

  // Is it a form submitting
  if (isset($options['form'])) $formData = 'jQuery(this).serialize()';
  elseif (isset($options['submit'])) $formData = '{\'#'.$options['submit'].'\'}.serialize()';
  elseif (isset($options['with'])) $formData = '\''.$options['with'].'\''; 

  // build the function
  $function = "jQuery.ajax({";
  $function .= 'type:\''.$method.'\'';
  $function .= ',dataType:\'' . $dataType . '\'';
  if (isset($type)) $function .= ',async:'.$type;
  if (isset($formData)) $function .= ',data:'.$formData;
  if (isset($update_success) and !isset($callback_success)) $function .= ',success:function(data, textStatus){jQuery(\''.$update_success.'\').'.$updateMethod.'(data);}';
  if (isset($update_failure)) $function .= ',error:function(XMLHttpRequest, textStatus, errorThrown){'.$update_failure.'}';
  if (isset($callback_loading)) $function .= ',beforeSend:function(XMLHttpRequest){'.$callback_loading.'}';
  if (isset($callback_complete)) $function .= ',complete:function(XMLHttpRequest, textStatus){'.$callback_complete.'}';
  if (isset($callback_success)) $function .= ',success:function(data, textStatus){'.$callback_success.'}';
  $function .= ',url:\''.url_for($options['url']).'\'';
  $function .= '})';

  if (isset($options['before']))
  {
    $function = $options['before'].'; '.$function;
  }
  if (isset($options['after']))
  {
    $function = $function.'; '.$options['after'];
  }
  if (isset($options['condition']))
  {
    $function = 'if ('.$options['condition'].') { '.$function.'; }';
  }
  if (isset($options['confirm']))
  {
    $function = "if (confirm('".escape_javascript($options['confirm'])."')) { $function; }";
    if (isset($options['cancel']))
    {
      $function = $function.' else { '.$options['cancel'].' }';
    }
  }

  return $function;
}

/**
   * Returns a form tag that will submit using XMLHttpRequest in the background instead of the regular
   * reloading POST arrangement. Even though it's using JavaScript to serialize the form elements, the form submission
   * will work just like a regular submission as viewed by the receiving side (all elements available in 'params').
   * The options for specifying the target with 'url' and defining callbacks are the same as 'link_to_remote()'.
   *
   * A "fall-through" target for browsers that don't do JavaScript can be specified
   * with the 'action'/'method' options on '$options_html'
   *
   * Example:
   *  <?php echo form_remote_tag(array(
   *    'url'      => '@tag_add',
   *    'update'   => 'question_tags',
   *    'loading'  => "Element.show('indicator'); \$('tag').value = ''",
   *    'complete' => "Element.hide('indicator');".visual_effect('highlight', 'question_tags'),
   *  )) ?>
   *
   * The hash passed as a second argument is equivalent to the options (2nd) argument in the form_tag() helper.
   *
   * By default the fall-through action is the same as the one specified in the 'url'
   * (and the default method is 'post').
   */
function jq_form_remote_tag($options = array(), $options_html = array())
{
  $options = _parse_attributes($options);
  $options_html = _parse_attributes($options_html);

  $options['form'] = true;

  $options_html['onsubmit'] = jq_remote_function($options).'; return false;';
  $options_html['action'] = isset($options_html['action']) ? $options_html['action'] : url_for($options['url']);
  $options_html['method'] = isset($options_html['method']) ? $options_html['method'] : 'post';

  return tag('form', $options_html, true);
}





  /**
   * Returns a JavaScript snippet to be used on the AJAX callbacks for starting
   * visual effects.
   *
   * 
   * Visual effect support 3 optionnal options :  callback,  speed, opacity.  Not all effect does support all options.
   * 
   * List of effects (options that supported by this effect)
   * Effects:
   *         - hide(speed, callback)
   *         - show(speed, callback)
   *         - slideDown(speed, callback)
   *         - slideUp(speed, callback)
   *         - slideToggle(speed, callback)
   *         - fadeIn(speed, callback)
   *         - fadeOut(speed, callback)
   *         - fadeTo(speed, opacity, callback)
   *         - toggle
   *  
   * 
   * 
   * Example of effect that support speed + callback:
   *  <?php echo link_to_remote('Reload', array(
   *        'update'  => 'posts',
   *        'url'     => '@reload',
   *        'complete => visual_effect('fade', '#posts', array('speed' => 'slow', 'callback' => 'function(){$("post_content").css("background", "yellow")}' )),
   *  )) ?>
   *  
   * Speed support 4 arguments : 'fast', 'normal', 'slow', number_in_miliseconds
   * 
   * 
   *    
   * Example of effect that support speed + opacity + callback:
   *  <?php echo link_to_remote('Reload', array(
   *        'update'  => 'posts',
   *        'url'     => '@reload',
   *        'complete => visual_effect('fadeTo', '#posts', array('speed' => 'slow', 'opacity' => '0.33', 'callback' => 'function(){$("post_content").css("background", "yellow")}' )),
   *  )) ?>
   *  
   * Opacity must be between 0 and 1, if none are specify or not between 0 and 1m, it assumes 0.5(default value)
   * 
   * 
   * 
   *  Element is optional so if you dont specify it assumes current element
   *  Example
   *  <?php echo form_to_remote(array(
   *        'update'  => 'posts',
   *        'url'     => '@reload',
   *        'complete => visual_effect('hide'),
   *  )) ?>
   *
   * This would hide the form when request is completed
   * 
   * 
   *
   * Fore more information check the jquery doc
   * http://http://docs.jquery.com/Effects.
   */
  function jq_visual_effect($effect, $element_id = false, $js_options = array())
  {
     
    //format slide /fade effect name correctly.
    if(preg_match("/^(slide|fade)/i", $effect, $matches))
    {
	   $count = strtolower($matches[1]) == 'fade'? 3 : 4;
       $effect = preg_replace("/(^|_|-)+(.)/e", '', $effect); //remove non alpha char
       $effect = preg_replace('/\ +/', '', $effect);  //remove space       
       
                                
         
	   $effect = trim(strtolower($matches[1]).ucfirst(strtolower(substr($effect, $count)))); 
   }
    else
    {
	  $effect = trim(strtolower($effect));
    }
    
	$element = $element_id ? "'$element_id'" : 'this';
    
    //Building speed
    $speed = isset($js_options['speed'])? is_numeric($js_options['speed'] )?$js_options['speed'] : "'". $js_options['speed'] ."'": "'normal'";

    //Building opacty                                   
    $opacity = isset($js_options['opacity']) && is_numeric($js_options['opacity'] )?$js_options['opacity'] >= 0 && $js_options['opacity'] <= 1?$js_options['opacity'] :0.5:0.5;

    //Building callback
    $callback =  isset($js_options['callback']) ? ", ".  $js_options['callback'] :null;                                                                         
     


    if(in_array($effect, array('hide', 'show','slideDown', 'slideUp', 'slideToggle', 'fadeIn', 'fadeOut')))
    {
        return  sprintf("jQuery(%s).%s(%s %s );", $element, $effect, $speed, $callback);  
    }
    elseif($effect == "fadeTo")
    {
        return  sprintf("jQuery(%s).%s(%s, %s %s);", $element, $effect, $speed, $opacity, $callback); 
    }
    else
    {
        return  sprintf("jQuery(%s).%s();", $element, $effect);    
    }
  }


/**
   *  Returns a button input tag that will submit form using XMLHttpRequest in the background instead of regular
   *  reloading POST arrangement. The '$options' argument is the same as in 'form_remote_tag()'.
   */
function jq_submit_to_remote($name, $value, $options = array(), $options_html = array())
{
  $options = _parse_attributes($options);
  $options_html = _parse_attributes($options_html);

  if (!isset($options['with']))
  {
    $options['with'] = 'jQuery(this.form.elements).serialize()';
  }

  $options_html['type'] = 'button';
  $options_html['onclick'] = jq_remote_function($options).'; return false;';
  $options_html['name'] = $name;
  $options_html['value'] = $value;

  return tag('input', $options_html, false);
}


  /**
   *  Returns a image submit tag that will submit form using XMLHttpRequest in the background instead of regular
   *  reloading POST arrangement. The '$options' argument is the same as in 'form_remote_tag()'.
   */
function jq_submit_image_to_remote($name, $source, $options = array(), $options_html = array())
{
  $options = _parse_attributes($options);
  $options_html = _parse_attributes($options_html);

  if (!isset($options['with']))
  {
    $options['with'] = 'jQuery(this.form.elements).serialize()';
  }

  $options_html['type'] = 'image';
  $options_html['onclick'] = jq_remote_function($options).' return false;';
  $options_html['name'] = $name;
  $options_html['src'] = image_path($source);

  if (!isset($options_html['alt'])) 
  {
    $path_pos = strrpos($source, '/');
    $dot_pos = strrpos($source, '.');
    $begin = $path_pos ? $path_pos + 1 : 0;
    $nb_str = ($dot_pos ? $dot_pos : strlen($source)) - $begin;
    $options_html['alt'] = ucfirst(substr($source, $begin, $nb_str));
  }

  return tag('input', $options_html, false);
}



function _update_method($position) {
  // Updating method
  $updateMethod = 'html';
  switch ($position) {
    case 'before':$updateMethod='before';break;
    case 'after':$updateMethod='after';break;
    case 'top':$updateMethod='prepend';break;
    case 'bottom':$updateMethod='append';break;
  }

  return $updateMethod;
}
           
/***  This is a wrapper for the JavascriptHelper function  ***/
function jq_link_to_function($name, $function, $html_options= array())
{
  return link_to_function($name, $function, $html_options);
}


/***  This is a wrapper for the JavascriptHelper function  ***/
function jq_button_to_function($name, $function, $html_options = array())
{
    return button_to_function($name, $function, $html_options);
}


/***  This is a wrapper for the JavascriptHelper function  ***/
function jq_javascript_tag($content = null)  
{
  return javascript_tag($content);  
}



/***  This is a wrapper for the JavascriptHelper function  ***/
function jq_javascript_cdata_section($content)
{
  return javascript_cdata_section($content);
}


/***  This is a wrapper for the JavascriptHelper function  ***/
function jq_if_javascript()
{
  return if_javascript();
}


/***  This is a wrapper for the JavascriptHelper function  ***/
function jq_end_javascript_tag()  
{
  return end_javascript_tag();  
}







